package com.zmj.sy.mom.srv.aps.utils.algorithm;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zmj.sy.mom.srv.aps.bean.bo.*;
import com.zmj.sy.mom.srv.aps.bean.entity.base.BaseEntity;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ApsDetailWeekday;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ApsWorkDetail;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ApsWorkOrder;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ReverseDetail;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.Group;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.Station;
import com.zmj.sy.mom.srv.aps.mapper.ApsDetailWeekdayMapper;
import com.zmj.sy.mom.srv.aps.mapper.ApsWorkDetailMapper;
import com.zmj.sy.mom.srv.aps.mapper.ApsWorkOrderMapper;
import com.zmj.sy.mom.srv.aps.mapper.ReverseDetailMapper;
import com.zmj.sy.mom.srv.aps.utils.Aps2Utils;
import com.zmj.sy.mom.srv.aps.utils.MkDateTimeUtils;
import com.zmj.sy.mom.srv.aps.utils.SyExceptionUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * APS瓶颈节点算法
 * 算法核心
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class ApsBottleneckAlgorithm implements ApsAlgorithm {

    private final ApsWorkOrderMapper apsWorkOrderMapper;

    private final ApsDetailWeekdayMapper apsDetailWeekdayMapper;

    private final ApsWorkDetailMapper apsWorkDetailMapper;
    private final ReverseDetailMapper reverseDetailMapper;


    @Override
    public void scheduleTask(ApsFactoryCache apsFactoryCache, ApsOrderCache apsOrderCache) {

        apsFactoryCache.insertDay(3, apsDetailWeekdayMapper, apsWorkDetailMapper);
        Map<Integer, Station> stationIdMap = apsFactoryCache.getStations().stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        // 打印待排产的任务列表
        List<Integer> reverseDetailIdList = apsOrderCache.getTaskList().stream().map(e -> e.getApsWorkDetail().getReverseDetailId()).distinct().collect(Collectors.toList());
        List<ReverseDetail> reverseDetails = reverseDetailMapper.selectBatchIds(reverseDetailIdList);
        Map<Integer, ReverseDetail> reverseDetailIdMap = reverseDetails.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<DiffTime> diffTimeList = apsOrderCache.getTaskList()
                .stream()
                .sorted((e1, e2) -> {
                    LocalDateTime e1Time = reverseDetailIdMap.get(e1.getApsWorkDetail().getReverseDetailId()).getReverseEndTime();
                    LocalDateTime e2Time = reverseDetailIdMap.get(e2.getApsWorkDetail().getReverseDetailId()).getReverseEndTime();
                    int timeCom = e2Time.compareTo(e1Time);
                    if(timeCom != 0){
                        return timeCom;
                    }
                    return reverseDetailIdMap.get(e1.getApsWorkDetail().getReverseDetailId()).getPhaseId().compareTo(reverseDetailIdMap.get(e1.getApsWorkDetail().getReverseDetailId()).getPhaseId());
                })
                .map(e -> new DiffTime(
                        e.getApsWorkDetail().getId(),
                        e.getApsWorkDetail().getMaterNo(),
                        e.getApsWorkDetail().getMaterName(),
                        e.getApsWorkDetail().getPhaseCode(),
                        e.getApsWorkDetail().getPlanStartDateTime(),
                        e.getApsWorkDetail().getPlanEndDateTime(),
                        e.getApsWorkDetail().getStationId()))
                .collect(Collectors.toList());
        Map<Integer, DiffTime> diffTimeIdMap = diffTimeList.stream().collect(Collectors.toMap(DiffTime::getId, Function.identity()));

        // 根据规则找到瓶颈的节点
        List<Integer> pingjingNodeId = apsOrderCache.getTaskList()
                .stream()
                .filter(e-> match(e, apsFactoryCache.getBottleneckPhaseCode()))
                .map(ApsTask::getApsWorkOrderId)
                .distinct()
                .collect(Collectors.toList());

        // 乱七八糟初始化
        // 找到瓶颈的节点后，找到平静节点的子节点重排，如果子节点也有瓶颈节点刚跳过。
        Map<Integer, List<ApsTask>> childrenMap = apsOrderCache.getTaskList().stream().filter(e->e.getApsWorkOrderPid() != null).sorted(Comparator.comparing(ApsTask::getApsWorkOrderPid)).collect(Collectors.groupingBy(ApsTask::getApsWorkOrderPid));
        Map<Integer, List<ApsTask>> apsWorkOrderIdMap = apsOrderCache.getTaskList().stream().collect(Collectors.groupingBy(ApsTask::getApsWorkOrderId));

        List<ApsTask> todoList = new ArrayList<>();
        for (Integer apsWorkOrderId : pingjingNodeId) {


            List<ApsTask> apsTasks = childrenMap.get(apsWorkOrderId);
            apsTasks.removeIf(e -> pingjingNodeId.contains(e.getApsWorkOrderId()));


            todoList.addAll(apsTasks);

            while(CollUtil.isNotEmpty(apsTasks)){
                List<ApsTask> temp = new ArrayList<>();

                List<Integer> apsParentIds = apsTasks.stream().map(ApsTask::getApsWorkOrderId).distinct().collect(Collectors.toList());
                for (Integer apsParentId : apsParentIds) {
                    List<ApsTask> apsTasks1 = childrenMap.get(apsParentId);

                    apsTasks.removeIf(e->pingjingNodeId.contains(e.getApsWorkOrderId()));
                    if(CollUtil.isEmpty(apsTasks1)){
                        continue;
                    }
                    temp.addAll(apsTasks1);
                }

                apsTasks = temp;
                if(CollUtil.isNotEmpty(apsTasks)){
                    todoList.addAll(apsTasks);
                }

            }

        }



        Map<Integer, ApsMachine> machineMap = apsFactoryCache.getMachines().stream().collect(Collectors.toMap(ApsMachine::getId, Function.identity()));

        removeAll(machineMap, todoList,apsOrderCache);

        Map<Integer, List<ApsTask>> taskSortGroupMap = todoList.stream().collect(Collectors.groupingBy(e -> e.getApsWorkDetail().getReverseDetailId(), Collectors.toList()));
        List<Integer> sortReverseIds = taskSortGroupMap.keySet()
                .stream()
                .sorted((e1, e2) -> {
                    LocalDateTime e1Time = reverseDetailIdMap.get(e1).getReverseEndTime();
                    LocalDateTime e2Time = reverseDetailIdMap.get(e2).getReverseEndTime();
                    return e2Time.compareTo(e1Time);
                })
                .collect(Collectors.toList());



        Map<Integer, List<ApsTask>> apsWorkOrderPidMap = new HashMap<>();
        for (Integer pid : apsWorkOrderIdMap.keySet()) {
            List<ApsTask> apsTasks = apsWorkOrderIdMap.get(pid);
            int minPhaseSeq = apsTasks.stream().mapToInt(ApsTask::getPhaseSeq).min().getAsInt();
            // 取最小工序的时间组，当成子节点的结束时间
            List<ApsTask> filter = apsTasks.stream().filter(e -> e.getPhaseSeq() == minPhaseSeq).collect(Collectors.toList());
            apsWorkOrderPidMap.put(pid, filter);
        }

//        System.out.println("-------------");


        for (Integer sortReverseId : sortReverseIds) {
            List<ApsTask> currentTaskList = taskSortGroupMap.get(sortReverseId);
            // 1.找到上道工序的最晚开始时间,校验后一道工序的截止时间
            List<ApsTask> apsTasks = apsWorkOrderIdMap.get(currentTaskList.get(0).getApsWorkOrderId());

            Optional<ApsTask> minApsTaskOp = apsTasks.stream().filter(e -> e.getApsWorkDetail().getPhaseSeq() > currentTaskList.get(0).getPhaseSeq()).min(Comparator.comparing(ApsTask::getPhaseSeq));
            if(minApsTaskOp.isPresent()){

                List<ApsTask> nextList = apsTasks.stream()
                        .filter(e -> e.getPhaseSeq().equals(minApsTaskOp.get().getPhaseSeq()))
                        .filter(e -> e.getConsumerStatus().equals(3))
                        .sorted(Comparator.comparing(ApsTask::getConsumerStatus).reversed())
                        .collect(Collectors.toList());

                // 下一道工序的结束时间就是此时的开始时间
                log.info("当前名称：{}, PLMID：{}, 工序：{} 开始时间：{}, 结束时间：{}, 上道工序：{}，最早开始时间：{}",
                        currentTaskList.get(0).getApsWorkDetail().getMaterName(),
                        currentTaskList.get(0).getApsWorkDetail().getMaterNo(),
                        currentTaskList.get(0).getApsWorkDetail().getPhaseCode(),
                        MkDateTimeUtils.toString(currentTaskList.get(0).getPlanStartDateTime()),
                        MkDateTimeUtils.toString(currentTaskList.get(0).getPlanEndDateTime()),
                        nextList.get(0).getApsWorkDetail().getPhaseCode(),
                        MkDateTimeUtils.toString(nextList.get(0).getPlanStartDateTime())
                );

                for (ApsTask nextTask : nextList) {
                    BigDecimal nextTotalCount = nextTask.getApsWorkDetail().getTotalCount();

                    // 找到所有没有占位的task
                    List<ApsTask> currentTaskNoConsumer = currentTaskList.stream()
                            .filter(e -> e.getConsumerStatus().equals(1) || e.getConsumerStatus().equals(2))
                            .sorted(Comparator.comparing(ApsTask::getConsumerStatus).reversed())
                            .collect(Collectors.toList());

                    // 填补占位，并排产

                    BigDecimal remainder = nextTotalCount;
                    for (ApsTask task : currentTaskNoConsumer) {
                        BigDecimal subtract = task.getApsWorkDetail().getTotalCount().subtract(task.getConsumerCount());
                        if(remainder.compareTo(subtract) > 0){
                            task.setConsumerCount(task.getConsumerCount().add(subtract));
                            task.setConsumerStatus(3);
                            remainder = remainder.subtract(subtract);
                        } else if(remainder.compareTo(subtract) == 0){
                            task.setConsumerCount(task.getConsumerCount().add(subtract));
                            task.setConsumerStatus(3);
                            remainder = remainder.subtract(subtract);
                        } else {
                            task.setConsumerCount(task.getConsumerCount().add(remainder));
                            task.setConsumerStatus(2);
                            remainder = BigDecimal.ZERO;
                        }

                        if(remainder.compareTo(BigDecimal.ZERO) == 0){
                            break;
                        }
                    }

                    for (ApsTask task : currentTaskList) {
                        task.getApsWorkDetail().setPlanEndDateTime(nextTask.getApsWorkDetail().getPlanStartDateTime());
                    }

                }

            } else {
                List<ApsTask> parent = apsWorkOrderPidMap.get(apsTasks.get(0).getApsWorkOrderPid());

                Optional<ApsTask> optionalApsTask = parent.stream().min(Comparator.comparing(ApsTask::getPlanStartDateTime));
                if (!optionalApsTask.isPresent()) {
                    continue;
                }
                ApsTask minTask = optionalApsTask.get();
                log.info("当前名称：{}, PLMID：{}, 工序：{} 开始时间：{}, 结束时间：{}, 父节点名称：{}, 父节点PLMID：{}，父节点工序：{}，父节点最早开始时间：{}",
                        currentTaskList.get(0).getApsWorkDetail().getMaterName(),
                        currentTaskList.get(0).getApsWorkDetail().getMaterNo(),
                        currentTaskList.get(0).getApsWorkDetail().getPhaseCode(),
                        MkDateTimeUtils.toString(currentTaskList.get(0).getPlanStartDateTime()),
                        MkDateTimeUtils.toString(currentTaskList.get(0).getPlanEndDateTime()),
                        parent.get(0).getApsWorkDetail().getMaterName(),
                        parent.get(0).getApsWorkDetail().getMaterNo(),
                        parent.get(0).getApsWorkDetail().getPhaseCode(),
                        MkDateTimeUtils.toString(minTask.getPlanStartDateTime())
                );
                List<ApsTask> parentList = parent.stream()
                        .filter(e -> minTask.getApsWorkDetail().getPhaseSeq().equals(e.getApsWorkDetail().getPhaseSeq()))
                        .sorted(Comparator.comparing(ApsTask::getPlanStartDateTime).reversed())
                        .collect(Collectors.toList());


                for (ApsTask parentTask : parentList) {
                    BigDecimal parentTotalCount = parentTask.getApsWorkDetail().getTotalCount();

                    // 找到所有没有占位的task
                    List<ApsTask> currentTaskNoConsumer = currentTaskList.stream()
                            .filter(e -> e.getConsumerStatus().equals(1) || e.getConsumerStatus().equals(2))
                            .sorted(Comparator.comparing(ApsTask::getConsumerStatus).reversed())
                            .collect(Collectors.toList());

                    // 填补占位，并排产
                    BigDecimal parentConsumerTotal = parentTotalCount.multiply(currentTaskList.get(0).getApsWorkDetail().getPartCount());

                    List<ApsTask> taskList = new ArrayList<>();

                    BigDecimal remainder = parentConsumerTotal;
                    for (ApsTask task : currentTaskNoConsumer) {

                        BigDecimal subtract = task.getApsWorkDetail().getTotalCount().subtract(task.getConsumerCount());
                        taskList.add(task);
                        if(remainder.compareTo(subtract) > 0){
                            task.setConsumerCount(task.getConsumerCount().add(subtract));
                            task.setConsumerStatus(3);
                            remainder = remainder.subtract(subtract);
                        } else if(remainder.compareTo(subtract) == 0) {
                            task.setConsumerCount(task.getConsumerCount().add(subtract));
                            task.setConsumerStatus(3);
                            remainder = remainder.subtract(subtract);

                        } else {
                            task.setConsumerCount(task.getConsumerCount().add(remainder));
                            task.setConsumerStatus(2);
                            remainder = BigDecimal.ZERO;
                        }

                        if(remainder.compareTo(BigDecimal.ZERO) == 0){
                            break;
                        }
                    }

                    for (ApsTask task : taskList) {
                        task.getApsWorkDetail().setPlanEndDateTime(parentTask.getApsWorkDetail().getPlanStartDateTime());
                    }

                }

            }

            List<ApsMachine> machines = apsFactoryCache.getGroupCodeMachineMap().get(currentTaskList.get(0).getGroupCode());
            for (ApsTask currentTask : currentTaskList) {
                LocalDateTime start = currentTask.getApsWorkDetail().getPlanEndDateTime();

                // 3.把此工序在该列表中依次排产
                List<ApsDetailWeekdayWrap> l = new ArrayList<>();
                for (ApsMachine machine : machines) {
                    if (start == null) {
                        throw SyExceptionUtils.e("排产时没有开始时间");
                    }

//                    if(currentTask.getPhaseCode().equals(apsFactoryCache.getPzCode())){
//                        start = start.minusSeconds(apsFactoryCache.getPzSecond());
//                    }

                    ApsDetailWeekdayWrap scheduling = Aps2Utils.schedulingBottleneck(apsFactoryCache, apsOrderCache, start, machine, machines, currentTask, apsDetailWeekdayMapper, apsWorkDetailMapper);
                    l.add(scheduling);
                }

                // 4.取出时间最靠后的一次排产结果
                ApsDetailWeekdayWrap calendarWrap = l.stream().filter(e-> e.getStartDateTime() != null && e.getEndDateTime() != null).max(Comparator.comparing(ApsDetailWeekdayWrap::getStartDateTime)).orElseThrow(() -> SyExceptionUtils.e("排产异常"));

                currentTask.getApsWorkDetail().setPlanStartDateTime(calendarWrap.getStartDateTime());
                currentTask.getApsWorkDetail().setPlanEndDateTime(calendarWrap.getEndDateTime());
                currentTask.setNextTask(calendarWrap.getNext());
                calendarWrap.getPrevious().setNextTask(currentTask);
                currentTask.getApsWorkDetail().setStationId(calendarWrap.getMachine().getId());
                currentTask.setStartMachineCalendar(calendarWrap.getStartMachineCalendar());
                currentTask.setAll(calendarWrap.getAll());
                currentTask.getApsWorkDetail().setStatus(2);

                DiffTime diffTime = diffTimeIdMap.get(currentTask.getApsWorkDetail().getId());
                diffTime.setTargetPlanStartDateTime(calendarWrap.getStartDateTime());
                diffTime.setTargetPlanEndDateTime(calendarWrap.getEndDateTime());
                diffTime.setTargetStationId(calendarWrap.getMachine().getId());

//                System.out.println(diffTime);

                if(diffTime.getTargetPlanEndDateTime().isBefore(diffTime.getSourcePlanEndDateTime())){
//                    System.out.println("------------------");
                }



//                log.info("工位：{}, 修改后开始时间：{}, 修改后结束时间：{}, 当前名称：{}, PLMID：{}, 工序：{}, 修改前开始时间：{}, 修改前结束时间：{}", calendarWrap.getMachine().getId(), currentTask.getPlanStartDateTime(),  currentTask.getPlanEndDateTime(), currentTask.getApsWorkDetail().getMaterName(), currentTask.getApsWorkDetail().getMaterNo(), currentTask.getApsWorkDetail().getPhaseCode(), startTemp, endTemp);
//                addLine(lines, calendarWrap.getMachine().getId(), currentTask.getPlanStartDateTime(),  currentTask.getPlanEndDateTime(), currentTask.getApsWorkDetail().getMaterName(), currentTask.getApsWorkDetail().getMaterNo(), currentTask.getApsWorkDetail().getPhaseCode(), startTemp, endTemp);
            }

            // 如果没有后一个工序


//            List<String> lines = diffTimeList.stream().map(DiffTime::toString).collect(Collectors.toList());
//            try {
//                FileUtils.writeLines(new File("/test/thanatos.txt"), lines);
//            } catch (IOException e) {
//                throw SyExceptionUtils.e(e);
//            }
        }



        Map<Integer, List<ApsTask>> collect = todoList.stream().collect(Collectors.groupingBy(ApsTask::getApsWorkOrderId));

        Map<Integer, ApsWorkOrder> workOrderIdMap = apsOrderCache.getWorkOrders().stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));


        for (Map.Entry<Integer, List<ApsTask>> entry : collect.entrySet()) {

            LambdaUpdateWrapper<ApsWorkOrder> owd = Wrappers.lambdaUpdate();
            owd.eq(ApsWorkOrder::getId, entry.getKey());
            LocalDateTime planStartDateTime = entry.getValue().stream().min(Comparator.comparing(ApsTask::getPlanStartDateTime)).get().getPlanStartDateTime();
            LocalDateTime planEndDateTime = entry.getValue().stream().max(Comparator.comparing(ApsTask::getPlanEndDateTime)).get().getPlanEndDateTime();

            ApsWorkOrder apsWorkOrder = workOrderIdMap.get(entry.getKey());
            apsWorkOrder.setPlanStartDateTime(planStartDateTime);
            apsWorkOrder.setPlanEndDateTime(planEndDateTime);


            owd.set(ApsWorkOrder::getPlanStartDateTime, apsWorkOrder.getPlanStartDateTime());
            owd.set(ApsWorkOrder::getPlanEndDateTime, apsWorkOrder.getPlanEndDateTime());
            owd.set(ApsWorkOrder::getStatus, 1);
            apsWorkOrderMapper.update(null, owd);
        }



//        Map<Integer, StationGroup> stationGroupMap = apsFactoryCache.getStationGroups().stream().collect(Collectors.toMap(StationGroup::getStationId, e -> e));
        Map<Integer, Group> groupMap = apsFactoryCache.getGroups().stream().collect(Collectors.toMap(Group::getId, Function.identity()));
        List<ApsDetailWeekday> detailWeekdays = new ArrayList<>();
        for (ApsTask task : todoList) {
            ApsWorkDetail detail = task.getApsWorkDetail();

            Station station = stationIdMap.get(detail.getStationId());
//            StationGroup stationGroup = stationGroupMap.get(detail.getStationId());
            Group group = groupMap.get(station.getGroupId());
            detail.setGroupId(group.getId());
            detail.setGroupCode(group.getMyCode());


            LambdaUpdateWrapper<ApsWorkDetail> owd = Wrappers.lambdaUpdate();
            owd.eq(ApsWorkDetail::getId, detail.getId());
            owd.set(ApsWorkDetail::getPlanStartDateTime, task.getPlanStartDateTime());
            owd.set(ApsWorkDetail::getPlanEndDateTime, task.getPlanEndDateTime());
            owd.set(ApsWorkDetail::getStatus, 1); // 3 已排产

            owd.set(ApsWorkDetail::getGroupCode, detail.getGroupCode());
            owd.set(ApsWorkDetail::getGroupId, detail.getGroupId());
            owd.set(ApsWorkDetail::getStationId, detail.getStationId());

            apsWorkDetailMapper.update(null, owd);


            List<ApsWeekDayWrap> startMachineCalendar = task.getAll();
            for (ApsWeekDayWrap machineCalendar : startMachineCalendar) {
                ApsDetailWeekday calendar = new ApsDetailWeekday();

                calendar.setOrderId(detail.getOrderId());
                calendar.setApsOrderId(detail.getApsOrderId());
                calendar.setApsBomId(detail.getApsWorkOrderId());
                calendar.setPhaseId(detail.getPhaseId());
                calendar.setPhaseCode(detail.getPhaseCode());
                calendar.setPhaseName(detail.getPhaseName());
                calendar.setApsWorkOrderId(detail.getApsWorkOrderId());
                calendar.setApsWorkDetailId(detail.getId());
                calendar.setGroupId(detail.getGroupId());

                calendar.setWorkTime(machineCalendar.getSecond());
                calendar.setPlanStartDateTime(machineCalendar.getStart());
                calendar.setPlanEndDateTime(machineCalendar.getEnd());
                calendar.setShiftId(machineCalendar.getShiftId());
                calendar.setShiftSeq(machineCalendar.getShiftSeq());
                calendar.setShiftStartDateTime(machineCalendar.getShiftStartDateTime());
                calendar.setShiftEndDateTime(machineCalendar.getShiftEndDateTime());
                calendar.setShiftDay(machineCalendar.getShiftDay());
                calendar.setStationGroupId(detail.getStationGroupId());
                calendar.setStationId(detail.getStationId());
                calendar.setState(1); // 3 已排产
                calendar.setOrderType(apsOrderCache.getOrder().getOrderType());
                detailWeekdays.add(calendar);

            }
        }
        apsDetailWeekdayMapper.insertBatchSomeColumn(detailWeekdays);
        apsOrderCache.getDetailWeekdays().addAll(detailWeekdays);

    }

    public List<String> formatLines(List<Map<String, Object>> lines) {
        List<String> ll = new ArrayList<>();

//        List<Map<String, Object>> collect = lines.stream()
//                .sorted((e1, e2) -> {
//                    Integer i1 = (Integer) e1.get("id");
//                    Integer i2 = (Integer) e2.get("id");
//                    int i3 = i1.compareTo(i2);
//                    if (i3 != 0) {
//                        return i3;
//                    }
//
//                    LocalDateTime p1 = (LocalDateTime) e1.get("planStartDateTime");
//                    LocalDateTime p2 = (LocalDateTime) e2.get("planStartDateTime");
//                    return - p1.compareTo(p2);
//                })
//                .collect(Collectors.toList());


        for (Map<String, Object> map : lines) {
            String message = MessageFormatter.arrayFormat("工位：{}, 修改后开始时间：{}, 修改后结束时间：{}, 当前名称：{}, PLMID：{}, 工序：{} ",new Object[]{
                    map.get("id"), map.get("planStartDateTime"), map.get("planEndDateTime"), map.get("materName"), map.get("materNo"),
                    map.get("phaseCode")}).getMessage();
            ll.add(message);
        }

        return ll;

    }

    public void addLine(List<Map<String, Object>> lines, Integer id, LocalDateTime planStartDateTime, LocalDateTime planEndDateTime, String materName, String materNo, String phaseCode, LocalDateTime startTemp, LocalDateTime endTemp) {
        Map<String, Object> params = new HashMap<>();
        params.put("id", id);
        params.put("planStartDateTime", planStartDateTime);
        params.put("planEndDateTime", planEndDateTime);

        params.put("materName", materName);
        params.put("materNo", materNo);
        params.put("phaseCode", phaseCode);
        params.put("startTemp", startTemp);
        params.put("endTemp", endTemp);

        lines.add(params);
    }

    /**
     * 删除所有的任务
     *
     * @param machineMap
     * @param todoList
     * @param apsOrderCache
     */
    public void removeAll(Map<Integer, ApsMachine> machineMap, List<ApsTask> todoList, ApsOrderCache apsOrderCache) {

        for (ApsTask apsTask : todoList) {
            removeTask(machineMap.get(apsTask.getApsWorkDetail().getStationId()), apsTask);
        }

        List<Integer> detailIdList = todoList.stream().map(e->e.getApsWorkDetail().getId()).distinct().collect(Collectors.toList());
        QueryWrapper<ApsDetailWeekday> query = Wrappers.query();
        query.in("aps_work_detail_id", detailIdList);
        apsDetailWeekdayMapper.deleteByApsWorkDetailId(query);
        apsOrderCache.getDetailWeekdays().removeIf(e-> detailIdList.contains(e.getApsWorkDetailId()));

        for (ApsTask apsTask : todoList) {
            apsTask.getStartMachineCalendar().clear();
            apsTask.getAll().clear();
            apsTask.setNextTask(null);
            apsTask.setPreviewTask(null);
            apsTask.setConsumerStatus(1);
            apsTask.setConsumerCount(new BigDecimal(0));
            apsTask.getApsWorkDetail().setPlanEndDateTime(null);
            apsTask.getApsWorkDetail().setPlanStartDateTime(null);
        }

    }

    public void removeTask(ApsMachine apsMachine, ApsTask apsTask){
        ApsTask next = apsMachine.getNextTask();
        ApsStep pre = apsMachine;
        boolean b = false;
        while(next != null){
            if(next.getApsWorkDetail().getId().equals(apsTask.getApsWorkDetail().getId())){

                pre.setNextTask(next.getNextTask());
                if(next.getNextTask() != null){
                    next.getNextTask().setPreviewTask(pre);
                }

                b = true;
                break;
            }

            pre = next;
            next = next.getNextTask();
        }

        if(!b){
            throw SyExceptionUtils.e("没有找到该任务");
        }

    }

    public boolean match(ApsTask apsTask, List<String> bottleneckPhaseCode) {
        return bottleneckPhaseCode.contains(apsTask.getPhaseCode());
    }

    @Override
    public void scheduleWl(ApsFactoryCache apsFactoryCache, ApsOrderCache apsOrderCache) {

    }

    @Override
    public String getCode() {
        return APS_BOTTLENECK_ALGORITHM_CODE;
    }
}
